package cn.mw.cmdb.processor;

import cn.hutool.core.bean.BeanDesc;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.PropDesc;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.mw.cmdb.anno.CMDBHeader;
import cn.mw.cmdb.entity.InstanceInfo;
import cn.mw.cmdb.entity.InstanceInfoExtend;
import cn.mw.cmdb.entity.ModelInfo;
import cn.mw.cmdb.param.InstanceSearchParam;
import cn.mw.cmdb.param.ModelSearchParam;
import cn.mw.cmdb.param.TableSearchParam;
import cn.mw.cmdb.service.impl.CmdbServiceManage;
import cn.mw.cmdb.service.impl.CustomModelServiceImpl;
import cn.mw.cmdb.service.impl.InstanceServiceImpl;
import cn.mw.cmdb.view.StaticsViewModel;
import cn.mw.cmdb.view.ViewConvertContext;
import cn.mw.microMonitorCommon.api.user.MwUserApi;
import cn.mw.microMonitorCommon.entity.cmdb.TableHeaderItem;
import cn.mw.microMonitorCommon.security.dto.MwUser;
import cn.mw.microMonitorCommon.utils.DatabaseUtils;
import org.apache.commons.beanutils.PropertyUtils;

import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

import static cn.mw.microMonitorCommon.entity.cmdb.TableHeaderItem.flexNum;

/**
 * 模型列表通用Processor
 */
public class StaticsProcessorModel implements TableDataProccessor {
    private CmdbServiceManage cmdbServiceManage;

    private TableSearchParam tableDataParam;

    public StaticsProcessorModel(CmdbServiceManage cmdbServiceManage, TableSearchParam tableDataParam) {
        this.cmdbServiceManage = cmdbServiceManage;
        this.tableDataParam = tableDataParam;
    }

    @Override
    public List genData(TableDataProcessorContext context) throws Exception {
        CustomModelServiceImpl customModelService = (CustomModelServiceImpl) cmdbServiceManage.getModelService(CustomModelServiceImpl.ID);
        ModelSearchParam modelSearchParam = new ModelSearchParam();
        //获取指定分组下的所有普通模型列表
        if (tableDataParam != null) {
            BeanUtil.copyProperties(tableDataParam, modelSearchParam, CopyOptions.create().setIgnoreNullValue(true));
        }
        modelSearchParam.setGroupId(tableDataParam.getId());
//        modelSearchParam.setPage(null);
        List<ModelInfo> modelInfos = customModelService.doSelectShowNormalModelByPath(modelSearchParam);
        List<StaticsViewModel> ret = new ArrayList<>();
        if (null != modelInfos && modelInfos.size() > 0) {
            List<String> ids = modelInfos.stream().map(ModelInfo::getId).collect(Collectors.toList());
            InstanceServiceImpl instanceService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
            InstanceSearchParam instanceSearchParam = new InstanceSearchParam();
            PropertyUtils.copyProperties(instanceSearchParam, tableDataParam);
            instanceSearchParam.setModelIds(ids);
            instanceSearchParam.setPage(null);
            instanceSearchParam.removeSubCondition(DatabaseUtils.getFieldName(InstanceInfoExtend::getModelType));
            List<InstanceInfo> instanceInfos = instanceService.selectList(instanceSearchParam);
            Map<String, Long> countMap = instanceInfos.stream().collect(Collectors.groupingBy(s -> s.getModelId(), Collectors.counting()));


            List<Long> userIds = modelInfos.stream().map(ModelInfo::getCreater).collect(Collectors.toList());
            MwUserApi mwUserApi = (MwUserApi) context.get(ViewConvertContext.MwuserApiKey);
            List<MwUser> mwUsers = mwUserApi.getUsersByUserIds(userIds);
            Map<Long, String> userNampMap = new HashMap<>();
            if (null != mwUsers) {
                userNampMap = mwUsers.stream().collect(Collectors.toMap(MwUser::getId, MwUser::getUsername, (o1, o2) -> o1));
            }

            for (ModelInfo modelInfo : modelInfos) {
                StaticsViewModel modelStaticsView = new StaticsViewModel();
                modelStaticsView.extractFrom(modelInfo);

                modelStaticsView.setCreater(userNampMap.get(modelInfo.getCreater()));

                if (null != countMap) {
                    long num = null == countMap.get(modelInfo.getId()) ? 0 : countMap.get(modelInfo.getId());
                    modelStaticsView.setInstanceNum(num);
                } else {
                    modelStaticsView.setInstanceNum(0L);
                }
                ret.add(modelStaticsView);
            }
        }
        return ret;
    }

    @Override
    public List<TableHeaderItem> genDefaultTableHeader(Class clazz) throws Exception {
        BeanDesc desc = BeanUtil.getBeanDesc(clazz);
        Iterator<PropDesc> ite = desc.getProps().iterator();
        List<TableHeaderItem> tableHeaderItems = new ArrayList<>();
        while (ite.hasNext()) {
            PropDesc propDesc = ite.next();
            Field field = propDesc.getField();
            CMDBHeader annotation = field.getAnnotation(CMDBHeader.class);
            if (null != annotation) {
                TableHeaderItem item = new TableHeaderItem();
                item.setField(field.getName());
                item.setHeaderName(annotation.name());
                item.setVisible(annotation.visible());
                item.setFlex(flexNum);
                item.setParseType(annotation.relateDataProcesor());
                item.setPropertyTypeId(annotation.propertyTypeId());
                tableHeaderItems.add(item);
            }
        }
        return tableHeaderItems;
    }
}
